package com.common.service.index;

import com.common.base.DictionaryAware;
import com.common.constants.Constants;
import com.common.converter.JudicialCheckConverter;
import com.common.entity.casemanage.QCaseEntity;
import com.common.entity.department.DepartmentEntity;
import com.common.entity.department.QDepartmentEntity;
import com.common.entity.judicialcheck.JudicialCheckEntity;
import com.common.entity.judicialcheck.QJudicialCheckEntity;
import com.common.entity.personal.PersonalEntity;
import com.common.entity.personal.QPersonalEntity;
import com.common.entity.system.DictionaryEntity;
import com.common.entity.target.QTargetItemEntity;
import com.common.entity.target.TargetTypeEntity;
import com.common.global.BizException;
import com.common.global.BizServiceEnum;
import com.common.repository.casemanage.CaseRepository;
import com.common.repository.departmentjob.DepartmentRepository;
import com.common.repository.judicialcheck.JudicialCheckRepository;
import com.common.repository.judicialpersonal.PersonalRepository;
import com.common.repository.target.TargetTypeRepository;
import com.common.requestvo.index.JudicialCheckDetailsChartReqVo;
import com.common.requestvo.judicialcheck.JudicialTargetTypeSumCheckRankReqVo;
import com.common.service.judicialcheck.JudicialTargetTypeSumCheckService;
import com.common.vo.index.CaseDistributeVo;
import com.common.vo.index.JudicialCaseDistributeVo;
import com.common.vo.index.JudicialCheckChartVo;
import com.common.vo.index.JudicialDistributeVo;
import com.common.vo.judicialcheck.JudicialCheckVo;
import com.common.vo.judicialcheck.JudicialTargetTypeSumCheckVo;
import com.querydsl.core.QueryResults;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author johnny
 * @create 2021-05-18 8:48 下午
 **/
@Service
@Slf4j
@Transactional(rollbackOn = Exception.class)
public class IndexPageServiceImpl implements IndexPageService {


    private final JPAQueryFactory queryFactory;

    private final JudicialTargetTypeSumCheckService judicialTargetTypeSumCheckService;

    private final JudicialCheckRepository judicialCheckRepository;

    private final TargetTypeRepository targetTypeRepository;

    private final PersonalRepository personalRepository;

    private final DepartmentRepository departmentRepository;

    private final CaseRepository caseRepository;

    private QCaseEntity qCaseEntity = QCaseEntity.caseEntity;
    private QPersonalEntity qPersonalEntity = QPersonalEntity.personalEntity;

    public IndexPageServiceImpl(JPAQueryFactory queryFactory, JudicialTargetTypeSumCheckService judicialTargetTypeSumCheckService, JudicialCheckRepository judicialCheckRepository, TargetTypeRepository targetTypeRepository, PersonalRepository personalRepository, DepartmentRepository departmentRepository, CaseRepository caseRepository) {
        this.queryFactory = queryFactory;
        this.judicialTargetTypeSumCheckService = judicialTargetTypeSumCheckService;
        this.judicialCheckRepository = judicialCheckRepository;
        this.targetTypeRepository = targetTypeRepository;
        this.personalRepository = personalRepository;
        this.departmentRepository = departmentRepository;
        this.caseRepository = caseRepository;
    }

    @Override
    public List<JudicialDistributeVo> judicialDistribute() {
        List<JudicialDistributeVo> list = new ArrayList<>();
        QPersonalEntity qPersonalEntity = QPersonalEntity.personalEntity;
        QDepartmentEntity qDepartmentEntity = QDepartmentEntity.departmentEntity;
        QueryResults<Tuple> queryResults = queryFactory.select(qPersonalEntity.departmentId.count(), qDepartmentEntity.departmentName)
                .from(qPersonalEntity)
                .innerJoin(qDepartmentEntity).on(qDepartmentEntity.id.eq(qPersonalEntity.departmentId))
                .groupBy(qPersonalEntity.departmentId)
                .fetchResults();
        queryResults.getResults().forEach(tuple -> {
            Long count = tuple.get(0, Long.class);
            String departmentName = tuple.get(1, String.class);
            JudicialDistributeVo judicialDistributeVo = new JudicialDistributeVo();
            judicialDistributeVo.setDepartmentName(departmentName);
            judicialDistributeVo.setCount(count);
            list.add(judicialDistributeVo);
        });
        return list;
    }

    @Override
    public List<JudicialTargetTypeSumCheckVo> scoreChartRanking(JudicialTargetTypeSumCheckRankReqVo judicialTargetTypeSumCheckRankReqVo) {
        return judicialTargetTypeSumCheckService.scoreChartRanking(judicialTargetTypeSumCheckRankReqVo);
    }

    @Override
    public JudicialCheckChartVo scoreDetails(JudicialCheckDetailsChartReqVo judicialCheckDetailsChartReqVo) {

        JudicialCheckChartVo judicialCheckChartVo = null;
        if (checkParams(judicialCheckDetailsChartReqVo)) {

            String superTargetType = judicialCheckDetailsChartReqVo.getSuperTargetType();
            TargetTypeEntity targetTypeEntity = targetTypeRepository.findByName(superTargetType);
            if (targetTypeEntity != null) {
                Long personalId = judicialCheckDetailsChartReqVo.getPersonalId();
                PersonalEntity personalEntity = personalRepository.findById(personalId).orElse(null);
                if (personalEntity != null) {

                    DepartmentEntity departmentEntity = departmentRepository.findById(personalEntity.getDepartmentId()).orElse(null);
                    judicialCheckChartVo = new JudicialCheckChartVo();

                    List<JudicialCheckVo> checkVoList = new ArrayList<>();

                    QJudicialCheckEntity qJudicialCheckEntity = QJudicialCheckEntity.judicialCheckEntity;
                    QTargetItemEntity qTargetItemEntity = QTargetItemEntity.targetItemEntity;

                    //账号登录进来 需要查看当前账号 所需要填写的 指标项 所以要绑定 personalId 查询条件
                    JPAQuery<Tuple> jpaQuery = queryFactory.select(qJudicialCheckEntity, qTargetItemEntity.targetItemName)
                            .from(qJudicialCheckEntity)
                            .leftJoin(qTargetItemEntity).on(qTargetItemEntity.id.eq(qJudicialCheckEntity.targetItemId))
                            .where(qJudicialCheckEntity.year.eq(judicialCheckDetailsChartReqVo.getYear())
                                    .and(qJudicialCheckEntity.month.eq(judicialCheckDetailsChartReqVo.getMonth()))
                                    .and(qJudicialCheckEntity.personalId.eq(judicialCheckDetailsChartReqVo.getPersonalId()))
                                    //这里是 大类型id
                                    .and(qJudicialCheckEntity.targetSuperTypeId.eq(targetTypeEntity.getId())));
                    jpaQuery.fetchResults().getResults().forEach(tuple -> {
                        JudicialCheckEntity judicialCheckEntity = tuple.get(0, JudicialCheckEntity.class);
                        String targetItemName = tuple.get(1, String.class);
                        JudicialCheckVo judicialCheckVo = JudicialCheckConverter.INSTANCE.domain2vo(judicialCheckEntity);
                        judicialCheckVo.setTargetItemName(targetItemName);
                        checkVoList.add(judicialCheckVo);
                    });

                    judicialCheckChartVo.setJudicialCheckVos(checkVoList);
                    judicialCheckChartVo.setPersonalId(judicialCheckChartVo.getPersonalId());
                    judicialCheckChartVo.setPersonalName(personalEntity.getName());
                    assert departmentEntity != null;
                    judicialCheckChartVo.setDepartmentName(departmentEntity.getDepartmentName());
                    judicialCheckChartVo.setYear(judicialCheckDetailsChartReqVo.getYear());
                    judicialCheckChartVo.setMonth(judicialCheckDetailsChartReqVo.getMonth());
                    judicialCheckChartVo.setPersonalId(personalId);
                }
            } else {
                throw new BizException(BizServiceEnum.FIND_NOT_TARGET_TYPE);
            }
        }
        return judicialCheckChartVo;
    }

    @Override
    public List<CaseDistributeVo> caseDistribute() {

        List<CaseDistributeVo> caseDistributeVos = new ArrayList<>();

        //办结案件总数量
//        long caseEndDateCount = queryFactory.select(qCaseEntity)
//                .from(qCaseEntity)
//                .where(qCaseEntity.caseEndDate.isNotNull()
//                .and(qCaseEntity.caseType.in("")))
//                .fetchCount();
//
//        CaseDistributeVo caseEndDateCaseDistributeVo = new CaseDistributeVo();
//        caseEndDateCaseDistributeVo.setCount(caseEndDateCount);
//        caseEndDateCaseDistributeVo.setLabel(Constants.CASE_END);
//        caseEndDateCaseDistributeVo.setSortOrder(0);
//        caseDistributeVos.add(caseEndDateCaseDistributeVo);

        Set<String> caseTypeSet = DictionaryAware.CASE_INDEX_MAPPING_MAP.keySet();

        queryFactory.select(qCaseEntity.caseType, qCaseEntity.count())
                .from(qCaseEntity)
                .where(qCaseEntity.caseType.in(caseTypeSet)
                        .and(qCaseEntity.caseEndDate.isNotNull()))
                .groupBy(qCaseEntity.caseType)
                .fetch().forEach(tuple -> {
            String caseType = tuple.get(0, String.class);
            Long caseTypeCount = tuple.get(1, Long.class);
            CaseDistributeVo caseDistributeVo = new CaseDistributeVo();
            caseDistributeVo.setCount(caseTypeCount);
            caseDistributeVo.setLabel(DictionaryAware.CASE_INDEX_MAPPING_MAP.get(caseType).getValue());
            caseDistributeVo.setSortOrder(DictionaryAware.CASE_INDEX_MAPPING_MAP.get(caseType).getSortNum());
            caseDistributeVos.add(caseDistributeVo);
        });

        //TODO initData 暂且固定值
        initFakeData(caseDistributeVos);

        long sum = caseDistributeVos.stream().mapToLong(CaseDistributeVo::getCount).sum();
        CaseDistributeVo caseEndDateCaseDistributeVo = new CaseDistributeVo();
        caseEndDateCaseDistributeVo.setCount(sum);
        caseEndDateCaseDistributeVo.setLabel(Constants.CASE_END);
        caseEndDateCaseDistributeVo.setSortOrder(0);
        caseDistributeVos.add(caseEndDateCaseDistributeVo);

        return caseDistributeVos.stream().sorted(
                Comparator.comparing(CaseDistributeVo::getSortOrder)
        ).collect(Collectors.toList());
    }

    private void initFakeData(List<CaseDistributeVo> caseDistributeVos) {
        DictionaryAware.CASE_INDEX_MAPPING_MAP
                .values().stream().map(DictionaryEntity::getValue)
                .filter(type -> {
                    List<String> collect = caseDistributeVos.stream().map(CaseDistributeVo::getLabel).collect(Collectors.toList());
                    if (collect.contains(type)) {
                        return false;
                    } else {
                        return true;
                    }
                }).collect(Collectors.toList()).forEach(noCaseType -> {
            CaseDistributeVo caseEndDateCaseDistributeVo = new CaseDistributeVo();
            caseEndDateCaseDistributeVo.setCount(0L);
            caseEndDateCaseDistributeVo.setLabel(noCaseType);
            caseEndDateCaseDistributeVo.setSortOrder(1);
            caseDistributeVos.add(caseEndDateCaseDistributeVo);
        });

        CaseDistributeVo caseEndDateCaseDistributeVo = new CaseDistributeVo();
        caseEndDateCaseDistributeVo.setCount(117L);
        caseEndDateCaseDistributeVo.setLabel("民事行政办结案件");
        caseEndDateCaseDistributeVo.setSortOrder(4);
        caseDistributeVos.add(caseEndDateCaseDistributeVo);

        CaseDistributeVo caseEndDateCaseDistributeVo2 = new CaseDistributeVo();
        caseEndDateCaseDistributeVo2.setCount(11L);
        caseEndDateCaseDistributeVo2.setLabel("公益诉讼办结案件");
        caseEndDateCaseDistributeVo2.setSortOrder(5);
        caseDistributeVos.add(caseEndDateCaseDistributeVo2);

        CaseDistributeVo caseEndDateCaseDistributeVo3 = new CaseDistributeVo();
        caseEndDateCaseDistributeVo3.setCount(117L);
        caseEndDateCaseDistributeVo3.setLabel("控告申诉办结案件");
        caseEndDateCaseDistributeVo3.setSortOrder(6);
        caseDistributeVos.add(caseEndDateCaseDistributeVo3);

    }


    @Override
    public List<JudicialCaseDistributeVo> judicialCaseDistribute() {
        List<JudicialCaseDistributeVo> list = new ArrayList<>();
        queryFactory.select(qCaseEntity.caseType,
                qPersonalEntity.name, qCaseEntity.count())
                .from(qCaseEntity)
                .leftJoin(qPersonalEntity).on(qPersonalEntity.id.eq(qCaseEntity.personalId))
                .where(qCaseEntity.caseType.in(DictionaryAware.CASE_INDEX_JUDICIAL_TYPE))
                .groupBy(qCaseEntity.personalId, qCaseEntity.caseType)
                .fetch().forEach(tuple -> {
            String caseType = tuple.get(0, String.class);
            String personalName = tuple.get(1, String.class);
            Long count = tuple.get(2, Long.class);
            JudicialCaseDistributeVo judicialCaseDistributeVo = new JudicialCaseDistributeVo();
            judicialCaseDistributeVo.setCount(count);
            judicialCaseDistributeVo.setPersonalName(personalName);
            judicialCaseDistributeVo.setType(caseType);
            list.add(judicialCaseDistributeVo);
        });
        return list;
    }

    boolean checkParams(JudicialCheckDetailsChartReqVo judicialCheckDetailsChartReqVo) {
        return judicialCheckDetailsChartReqVo.getPersonalId() != null && judicialCheckDetailsChartReqVo.getPersonalId() != 0
                && judicialCheckDetailsChartReqVo.getYear() != null && judicialCheckDetailsChartReqVo.getYear() != 0
                && judicialCheckDetailsChartReqVo.getMonth() != null && judicialCheckDetailsChartReqVo.getMonth() != 0
                && StringUtils.isNotEmpty(judicialCheckDetailsChartReqVo.getSuperTargetType());

    }
}